package com.supply.hsa.link.task.fetch.hotel;

import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.ReentrantLock;

import com.supply.hsa.link.common.constant.SupplierClass;
import com.supply.hsa.link.task.fetch.*;
import com.supply.hsa.link.task.fetch.hotel.container.TaskHandlerContainer;
import com.supply.hsa.link.task.fetch.hotel.dto.CommonSyncRequest;
import com.supply.hsa.link.task.fetch.enums.SyncTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;



/**
 * 
 * 抓取全部产品定时器任务执行器
 *
 */
@Service
@Slf4j
public class HotelTimerTaskExecutor implements TaskExecutor<HotelTimerTask> {

	@Autowired
	@Qualifier("fetchHotelTaskExecutor")
	private TaskExecutor<FetchHotelTask> taskExecutor;
	
	@Autowired
	private TaskHandlerContainer taskHandlerContainer;
	
	private ConcurrentMap<SupplierClass, WorkerStatus> workerStatusMap = new ConcurrentHashMap<SupplierClass, WorkerStatus>();
	
	private final ReentrantLock countLock = new ReentrantLock();
	
	private boolean validTask(HotelTimerTask task){
		if(task == null || task.getSupplierClass() == null){
			return false;
		}
		
		return true;
	}
	
	@Override
	public void add(HotelTimerTask task) {
		if(!validTask(task)){
			return;
		}
		
		if(this.taskHandlerContainer.getTaskHandler(task.getSupplierClass()) == null){
			throw new RuntimeException(task.getSupplierClass() + "未注册TaskHandler,不能执行定时器任务");
		}
		
		//一个供应商的定时器任务未结束前，不能启动新的任务
		if(workerStatusMap.putIfAbsent(task.getSupplierClass(), WorkerStatus.RUNNING) != null){
			throw new RuntimeException(task.getSupplierClass() + "存在未执行完的定时器任务");
		}
		
		this.execute(task);
	}
	
	@Override
	public void execute(HotelTimerTask task) {
		if(!validTask(task)){
			return;
		}
		
		log.info(task.getSupplierClass() + "开始执行定时器任务.");
		
		//初始化任务
        task.initTask();
        //任务状态
        task.setWorkStatus(WorkerStatus.RUNNING);
        //任务类型
        task.setTaskName(CommonConstant.TaskType.TIMER_TASK);
		
        List<CommonSyncRequest> commonSyncRequestList = null;
        try {
        	TaskHandler taskHandler = this.taskHandlerContainer.getTaskHandler(task.getSupplierClass());
            commonSyncRequestList = taskHandler.getSyncRequestOfTimerTask(task.getSupplierClass(), task.getSupplierCode(), task.getFreqId());
            if(CollectionUtils.isEmpty(commonSyncRequestList)){
            	log.info(task.getSupplierClass() + "定时器任务请求对象数量为0.");
            	
            	task.setResult(false);
            	this.finish(task);
            	return;
            }
		} catch (Exception e) {
			log.error("同步酒店产品异常，供应商：{}",task.getSupplierClass(), e);
			
			task.setResult(false);
			this.finish(task);
			
			return;
		}
        
        //注册任务时写日志
        task.setEnableLog(true);
        //任务总数
        task.getTaskResult().setTaskCount(Long.valueOf(commonSyncRequestList.size()));
        
        //注册任务; 并会立马写日志
        TaskManager.getInstance().register(task);
        
        for(CommonSyncRequest commonSyncRequest : commonSyncRequestList){
        	FetchHotelTask fetchRemoteTask = new FetchHotelTask();
    		fetchRemoteTask.setParentTaskId(task.getTaskId());
    		fetchRemoteTask.setSupplierClass(task.getSupplierClass());
    		fetchRemoteTask.setRequest(commonSyncRequest);
    		taskExecutor.add(fetchRemoteTask);
        }
	}

	/**
	 * 当停止定时器任务时，待执行的抓取数据任务全部取消;
	 * 
	 * FetchHotelTaskExecutor处理;
	 */
	@Override
	public void stop(HotelTimerTask task) {
		if(!validTask(task)){
			log.info("不存在在运行的定时器任务.");
			return;
		}
		
		WorkerStatus status = workerStatusMap.get(task.getSupplierClass());
		if(status == null){
			log.info(task.getSupplierClass() + "不存在在运行的定时器任务,停止任务失败.");
			return;
		}
		
		//运行或暂停状态才可停止
		if(!(status.equals(WorkerStatus.RUNNING) || status.equals(WorkerStatus.PAUSING))){
			log.info(task.getSupplierClass() + "不存在在运行的定时器任务,停止任务失败,定时器任务状态为:" + status);
			return;
		}
		
		log.info(task.getSupplierClass() + "开始停止定时器任务.");
		
		task.setWorkStatus(WorkerStatus.STOPPED);
		workerStatusMap.put(task.getSupplierClass(), task.getWorkStatus());
	}
	
	/**
	 * 暂停运行中全部待抓取数据任务;
	 * 
	 * FetchHotelTaskExecutor处理;
	 */
	@Override
	public void pause(HotelTimerTask task) {
		if(!validTask(task)){
			log.info("不存在在运行的定时器任务.");
			return;
		}
		
		WorkerStatus status = workerStatusMap.get(task.getSupplierClass());
		if(status == null){
			log.info(task.getSupplierClass() + "不存在在运行的定时器任务,暂停任务失败.");
			return;
		}
		
		//运行状态才可暂停
		if(!status.equals(WorkerStatus.RUNNING)){
			log.info(task.getSupplierClass() + "不存在在运行的定时器任务,暂停任务失败,定时器任务状态为:" + status);
			return;
		}
		
		log.info(task.getSupplierClass() + "开始暂停定时器任务.");
		
		task.setWorkStatus(WorkerStatus.PAUSING);
		workerStatusMap.put(task.getSupplierClass(), task.getWorkStatus());
	}

	/**
	 * 恢复暂停状态的待抓取数据任务；
	 * 
	 * FetchHotelTaskExecutor处理;
	 */
	@Override
	public void resume(HotelTimerTask task) {
		if(!validTask(task)){
			log.info("不存在暂停的定时器任务.");
			return;
		}
		
		WorkerStatus status = workerStatusMap.get(task.getSupplierClass());
		if(status == null){
			log.info(task.getSupplierClass() + "不存在暂停的定时器任务,恢复任务失败.");
			return;
		}
		
		//暂停状态才可恢复
		if(!status.equals(WorkerStatus.PAUSING)){
			log.info(task.getSupplierClass() + "不存在暂停的定时器任务,恢复任务失败,定时器任务状态为:" + status);
			return;
		}
		
		log.info(task.getSupplierClass() + "开始恢复暂停的定时器任务.");
		
		task.setWorkStatus(WorkerStatus.RUNNING);
		workerStatusMap.put(task.getSupplierClass(), task.getWorkStatus());
	}

	@Override
	public void finish(HotelTimerTask task) {
		if(!validTask(task)){
			return;
		}
		
		log.info(task.getSupplierClass() + "定时器任务执行完毕.");
		
		task.setWorkStatus(WorkerStatus.FINISH);
		task.setEndDate(new Date());
		
		//清除本次任务, 使的下次定时任务能够执行
		workerStatusMap.remove(task.getSupplierClass());
		
		TaskManager.getInstance().unregister(task);
	}
}
